package NetFrameWork

import (
	"NetFrameWork/core/hub"
	"NetFrameWork/util/config"
	"NetFrameWork/util/crypt"
	"NetFrameWork/util/packet"
	"NetFrameWork/util/random"

	"time"

	"fmt"
	"log"
	"net"
	"sync"
	"sync/atomic"
)

type connCloseCallBack func(conn hub.Conn)

type Server struct {
	addr          string
	threadCount   int64
	mutex         *sync.RWMutex
	handler       packet.PacketHandler
	hub           hub.ConHub
	stopChan      chan bool
	CloseCallBack connCloseCallBack
	nextId        uint64
}

func CreateTcpServer(handler packet.PacketHandler) *Server {
	err := config.InitConfig("server")
	if err != nil {
		//panic(err)
	}
	addr, err := config.GetConfig().GetString("listenAddr")
	if err != nil {
		log.Println("无法读取监听地址 设置默认:0.0.0.0:8484")
		addr = "0.0.0.0:8484"
	}
	count, err := config.GetConfig().GetInt64("threadCount")
	if err != nil {
		log.Println("无法读取监听业务处理线程数量 设置默认:10")
		count = 10
	}
	server := Server{
		threadCount: count,
		addr:        addr,
		mutex:       &sync.RWMutex{},
		handler:     handler,
		stopChan:    make(chan bool),
		nextId:      uint64(0),
	}
	return &server
}

func handShake(ver uint16, sendIv, recvIv []byte) []byte {
	pw := packet.NewPacketWriterWithCapacity(0)
	pw.WriteShort(15)
	pw.WriteUShort(ver)
	pw.WriteBytes(recvIv)
	pw.WriteBytes(sendIv)
	pw.WriteLong(time.Now().UnixNano() / 1e6)
	return pw.GetPacket()
}

func (this *Server) SetHub(conHub hub.ConHub) {
	this.hub = conHub
}

func (this *Server) SetCheckIdle(f func(server *Server)) {
	go func() {
		ticker := time.NewTicker(30 * time.Second)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				f(this)
			case <-this.stopChan:
				log.Println("超时检查协程已结束")
			}
		}
	}()
}

func (this *Server) GetHub() hub.ConHub {
	return this.hub
}

func (this *Server) Start() {
	listener, err := net.Listen("tcp", this.addr)
	if err != nil {
		panic(err)
	}
	go func() {
		for {
			select {
			case <-this.stopChan:
				log.Println(fmt.Sprintf("Closeing the Server child Thread %v", 0x01))
				return
			default:
				conn, err := listener.Accept()
				if err != nil {
					log.Println(err)
					continue
				}
				//sendIv := []byte{0,0,0,0}
				//recvIv := []byte{0,0,0,0}
				sendIv := Randomizer.NextBytes(make([]byte, 4))
				recvIv := Randomizer.NextBytes(make([]byte, 4))
				sendCrypto := CryptUtil.NewMapleAESOFB(&CryptUtil.AESKey, sendIv, 1, true)
				recvCrypto := CryptUtil.NewMapleAESOFB(&CryptUtil.AESKey, recvIv, 1, true)
				_, err = conn.Write(handShake(001, sendIv, recvIv))
				if err != nil {
					log.Println(err)
					continue
				}

				client := NewClientConnection(this, conn, sendCrypto, recvCrypto)
				fmt.Println("Client Online")
				//this.hub.AddCon(client)
				go client.read()

			}
		}
	}()

}

func NewPacketWriter() packet.PacketWriter {
	return packet.NewPacketWriter()
}

func NewPacketReader(d []byte) packet.PacketReader {
	return packet.NewPacketReader(d)
}

func (this *Server) getNextId() (id uint64) {
	if atomic.LoadUint64(&this.nextId) == 0 {
		atomic.StoreUint64(&this.nextId, 1)
	}
	id = atomic.LoadUint64(&this.nextId)
	atomic.AddUint64(&this.nextId, 1)
	return
}
